﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Factory;

namespace Basic.第一章
{
    public class Assembler //一个手动实现依赖注入的中间部分
    {
        /// <summary>
        /// 配置节名称
        /// </summary>
        private const string SectionName = "customFactories";

        /// <summary>
        /// 保存"抽象类型/实体类型"对应关系的字典
        /// </summary>
        private static readonly Dictionary<Type, Type> Dictionary = new Dictionary<Type, Type>();

        static Assembler()
        {
            //注册抽象类型需要使用的实体类型
            //实际的配置信息可以从外层机制获取，例如通过配置获取
            //Dictionary.Add(typeof(ITimerProvider), typeof(SystemTimeprovider));
            //Dictionary.Add(typeof(IFactory), typeof(FactoryA));//增加一个注册项

            var collection = (NameValueCollection)ConfigurationManager.GetSection(SectionName);
            for (var i = 0; i < collection.Count; i++)
            {
                var target = collection.GetKey(i);
                var source = collection[i];
                var targetType = Type.GetType(target);
                var sourceType = Type.GetType(source);
                if (targetType != null && sourceType != null)
                {
                    Dictionary.Add(targetType, sourceType);
                }
            }
        }

        /// <summary>
        /// 根据客户程序需要的抽象类型选择相应的实体类型，并返回类型实例
        /// </summary>
        /// <param name="type">实体类型实例</param>
        /// <returns></returns>
        public object Create(Type type)//主要用于非泛型方式调用
        {
            if ((type == null) || !Dictionary.ContainsKey(type)) throw new NullReferenceException();
            var targetType = Dictionary[type];
            return Activator.CreateInstance(targetType);
        }

        /// <summary>
        /// 抽象类型(抽象类/接口/或者某种基类)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T Create<T>()//主要用于泛型方式调用
        {
            return (T)Create(typeof(T));
        }
    }
}
